﻿#pragma once

#if defined(__EXCEPTIONS) ||_HAS_EXCEPTIONS > 0
#	include <exception>
#endif
#include <cstdio>
#include <cwchar>
#include "String.hpp"

#if defined(_MSC_VER)
#	pragma warning(disable:4290)
#endif

namespace helpers {

	namespace text {

		/// @addtogroup helper_text
		/// @{

		/// 字符串编制器模板
		/// 
		/// @param T 字符类型
		template <typename T>
		class basic_string_formater 
		{
		public:
			enum  {
				CacheSize = 128 ///< 对象内数据缓存容量
			};

			/// 构造函数.
			/// 此构造函数只构造出一个空的字符串编制器实例
			/// @param size 指定数据缓存的大小, 默认为 [#CacheSize]
			basic_string_formater(size_t size = CacheSize) throw(exception)
				: _dataPtr(size > CacheSize ? new T[size] : _data)
				, _dataLength(0)
				, _dataSize(size)
			{
				_dataPtr[0] = 0;
			}

			/// 构造函数(构造时附带格式化字符串文本).
			/// 通过传入字符串格式及参数快速完成字符串的格式化及格式化转换器实例的构造
			/// @param lhs 指定字符串格式, 兼容 [printf/sprintf...] 规范
			/// @param rhs 指定用于格式化字符串的参数
			/// @param size 指定数据缓冲区大小, 默认为 [#CacheSize]
			basic_string_formater(const T* lhs, const T* rhs, size_t size = CacheSize) throw(exception)
				: _dataPtr(size > CacheSize ? new T[size] : _data)
				, _dataLength(0)
				, _dataSize(size)
			{
				format(lhs, rhs);
			}

			/// 构造函数(构造时附带格式化不同类型的信息).
			/// 通过传入字符串格式及参数快速完成字符串的格式化及格式化转换器实例的构造
			/// @param lhs 指定字符串格式, 兼容 [printf/sprintf...] 规范
			/// @param rhs 指定用于格式化字符串的参数
			/// @param size 指定数据缓冲区大小, 默认为 [#CacheSize]
			template <typename V>
			basic_string_formater(const T* lhs, V rhs, size_t size = CacheSize) throw(exception)
				: _dataPtr(size > CacheSize ? new T[size] : _data)
				, _dataLength(0)
				, _dataSize(size)
			{
				format(lhs, rhs);
			}

			/// 析构函数.
			~basic_string_formater()
			{
				if (_dataSize > CacheSize)
					delete [] _dataPtr;
				_dataPtr = NULL;
			}

			/// 调用操作符.
			/// 将对像当成函数一样使用, 可用来进行字符串格式化操作
			/// @param lhs 字符串格式, 兼容 [#printf/#sprintf...] 规范
			/// @param rhs 格式参数
			/// @param size 指定需要的缓冲区大小
			/// @return 对象自身
			basic_string_formater<T>& operator()(const T* lhs, const T*rhs, size_t size = CacheSize) throw(exception)
			{
				format(lhs, rhs);
				return *this;
			}

			/// 调用操作符.
			/// 将对像当成函数一样使用, 可用来进行字符串格式化操作
			/// @param lhs 字符串格式, 兼容 [#printf/#sprintf...] 规范
			/// @param rhs 格式参数
			/// @return 对象自身
			template <typename V>
			basic_string_formater<T>& operator()(const T* lhs, V rhs) throw(exception)
			{
				format(lhs, rhs);
				return *this;
			}

			/// 字符型指针隐式转换操作符.
			/// @return 对象内数据指针
			operator const T*() const
			{
				return _dataPtr;
			}

			/// 获取对象内数据实际长度
			/// @return 对象内数据实际长度, 以字符为单位
			size_t length() const
			{
				return _dataLength;
			}

		protected:
			/// @internal
			/// 复制构造函数
			/// 复制此类对象毫无意义，所以禁止复制构造以免带来不利影响
			/// @endinternal
			basic_string_formater(const basic_string_formater<T>& rhs)
			{
			}

			/// @internal
			/// 复制构造函数
			/// 对此类对象进行赋值毫无意义，所以禁止赋值操作以免带来不利影响
			/// @endinternal
			basic_string_formater<T>& operator =(const basic_string_formater<T>& rhs)
			{
				return *this;
			}

			/// @internal
			/// @endinternal	
			void check_format_result(int r) throw(exception)
			{
				const char *error = NULL;
				if (r < 0)
					error = "bad arguments.";
				else if (r > static_cast<int>(_dataSize))
					error = "buffer is too small.";
				else
					_dataLength = static_cast<size_t>(r);
				if (error)
					throw std::exception(error);
			}

			/// @internal
			/// @endinternal	
			void format(const char* lhs, const char* rhs)
			{
				int n = std::snprintf(_dataPtr, _dataSize, lhs, rhs);
				check_format_result(n);
			}

			/// @internal
			/// @endinternal	
			void format(const wchar_t* lhs, const wchar_t* rhs)
			{
				int n = std::swprintf(_dataPtr, _dataSize, lhs, rhs);
				check_format_result(n);
			}

			/// @internal
			/// @endinternal	
			template <typename V>
			void format(const char* lhs, V rhs)
			{
				int n = std::snprintf(_dataPtr, _dataSize, lhs, rhs);
				check_format_result(n);
			}

			/// @internal
			/// @endinternal
			template <typename V>
			void format(const wchar_t* lhs, V rhs)
			{
				int n = std::swprintf(_dataPtr, _dataSize, lhs, rhs);
				check_format_result(n);
			}

		private:
			T _data[CacheSize]; ///< 对象内部缓存
			T* _dataPtr; ///< 数据指针
			size_t _dataLength; ///< 数据实际长度
			size_t _dataSize; ///< 数据最大容量

		}; // class basic_string_formater

		typedef basic_string_formater<char> StringFormater; ///< 窄字符型字符编制器
		typedef basic_string_formater<wchar_t> WStringFormater; ///< 宽字符型字符编制器

		/// @}

	} // namespace text;
} // namespace helpers

/// @ingroup helper_text_examples
/// @page example_basic_string_formater 字符串编制器
/// @code
/// #include <iostream>
/// #include <StringFormater.hpp>
/// int main(int argc, char** argv)
/// {
///     Text::StringFormater sf(4096);
///     std::cout << sf("file://%s", "test.txt");
///     std::cout << sf("%08X", 12345);
///     return 0;
/// }
/// @endcode

